package it.unibo.deis.lia.networkInterface;

import java.io.*;
import java.net.NetworkInterface;

import it.unibo.deis.lia.location.*;
//import it.unibo.deis.lia.simulator.*;

import java.util.Vector;
import org.apache.log4j.*;
import org.apache.log4j.net.*;

import com.sun.org.apache.bcel.internal.generic.IFNONNULL;

public class IEEE80211 extends GenericNetworkInterface /*implements Runnable*/{
	
//	private DeviceData deviceData=null; // simulation
//	private PhyDeviceSim pds=null; // simulation
	
	private boolean testing=Properties.testing;
	
	private boolean logging=Properties.logging; // true==>performance gathering mode
	//private Vector<Location> allowedMACs; // allowed remote interfaces
	private Vector<Location> allowedESSIDs; // allowed remote networks
	Logger logger=Logger.getRootLogger();
	
	private String connectRoleEssid=null;
	
	private Vector<NamedLocationOss> privateCachedRSSIVector=new Vector<NamedLocationOss>();
	private long lastRSSIScan=-1;
	
	private boolean connectorRole=false;
	private String connectorRoleIP;
	
	public IEEE80211() throws Exception{
		this(0);
	}
	public IEEE80211(int wirelessInterfaceNumber) throws Exception{
		//System.out.println("IEEE80211: System.getProperty(\"os.name\") "+System.getProperty("os.name"));
		if(wirelessInterfaceNumber>=0){
			if(System.getProperty("os.name").startsWith("Windows")){
				try{
					//System.out.println("./lib/80211UtilWindows.exe init");
					Process p2=Runtime.getRuntime().exec("./lib/80211UtilWindows.exe init");
					p2.waitFor();
					
					/*//InputStream stdoutStream = new BufferedInputStream(p2.getInputStream());
					InputStream stdoutStream = new BufferedInputStream(p2.getErrorStream());
					StringBuffer buffer= new StringBuffer();
					int c = stdoutStream.read();
					while(c!=-1){
						buffer.append((char)c);
						c = stdoutStream.read();
					}
					String outputText = buffer.toString();
					System.out.println("IEEE80211 init windows: "+outputText);/**/
					
					/*if(outputText.contains("Access is denied")){
						administratorRights=false;
					}*/
				}
				catch(Exception e){
					e.printStackTrace();
				}
				/*if(!administratorRights){
					//e.printStackTrace();
					System.err.println("IEEE80211: The program must be executed with administrator rights!!!");
					System.exit(-2);
				}*/
			}
			
			Vector<GenericNetworkInterface> interfaces=GenericNetworkInterface.getInterfaces();//getMacAddress();
			System.out.println("IEEE80211: interfaces "+interfaces);
			if(interfaces.size()==0)throw new Exception("There are no network interfaces");

			for(int i=0;i<interfaces.size()/*&&wirelessCount<=wirelessInterfaceNumber*/;i++){
				if(!isIEEE80211(interfaces.elementAt(i))){
					//System.out.println(interfaces.elementAt(i)+" is NOT wireless ");
					interfaces.removeElementAt(i);
					i--;
				}
			}
			if(interfaces.size()<=wirelessInterfaceNumber){
				throw new Exception("Interface "+wirelessInterfaceNumber+" does not exist, or is not IEEE 802.11, or is not fully supported (sorry...)\n" +
						"Do you have __Administrator Rights?__");
			}
			
			super.windowsNumber=interfaces.elementAt(wirelessInterfaceNumber).windowsNumber;
			super.hardwareAddress=interfaces.elementAt(wirelessInterfaceNumber).hardwareAddress;
			super.name=interfaces.elementAt(wirelessInterfaceNumber).name;
			super.description=interfaces.elementAt(wirelessInterfaceNumber).description;
			
			System.out.println("IEEE80211.this: "+this);
		}
/*		else if(wirelessInterfaceNumber==-1){
			pds=new PhyDeviceSim(new SimContext());
			deviceData=pds.getDeviceData();
			pds.start();

			super.hardwareAddress="00:11:22:33:44:55";
			super.name="Simulator";
			super.description="Simulator";
			//super.number=-1;
		}
*/
		else{
			throw new Exception("Wrong interface number: "+wirelessInterfaceNumber);
		}
		
		if(logging){
			logger.addAppender(new SocketAppender(Properties.ipLoggerServer,4545));
		}
		if(testing){
			/*allowedMACs=new Vector<Location>();
			allowedMACs.addElement(new Location("0011f67fec59")); // digicom usb
			allowedMACs.addElement(new Location("00022dbf8e32")); // orinoco con custodia
			allowedMACs.addElement(new Location("00022dbf3e33")); // orinoco senza custodia
			allowedMACs.addElement(new Location("0019d2961529")); // toshiba
			allowedMACs.addElement(new Location("0219d2")); // fake toshiba
			//allowedMACs.addElement(new Location("0219d22a96f4")); // fake toshiba
			//allowedMACs.addElement(new Location("0219d2014d23")); // fake toshiba
			//allowedMACs.addElement(new Location("0219d255bc27")); // fake toshiba
			allowedMACs.addElement(new Location("0013ce362de1")); // mini-dell*/
			
			allowedESSIDs=new Vector<Location>();
			
			//allowedESSIDs.addElement(new Location("SC-"));
			//allowedESSIDs.addElement(new Location("NE-"));
			allowedESSIDs.addElement(new Location("pippo"));
		}
	}

	public boolean isConnectorRole(){
		return connectorRole;
	}
	public String getConnectorRoleIP(){
		return connectorRoleIP;
	}
	
	public void setConnectorRole(String essid,String connectorAddress,String configPath/*GenericNetworkInterface externalInterface*/)throws Exception{
		if(connectorRole==false){
			connectorRoleIP=connectorAddress;
			notAllowedESSIDs.add(new Location(essid));
			
			connectorRole=true;
			if(System.getProperty("os.name").startsWith("Linux")){
				setConnectorRoleLinux(essid,configPath/*externalInterface*/);
			}
			else if(System.getProperty("os.name").startsWith("Windows")){	
				setConnectorRoleWindows(/*externalInterface*/);
			}
			else{
				connectorRole=false;
				throw new Exception("Not supported Operating System");
			}
		}
	}
	private void setConnectorRoleWindows(/*GenericNetworkInterface externalInterface*/)throws Exception{
		throw new Exception("IEEE80211.setConnectorRoleWindows not implemented: externalInterface ");//+externalInterface);
		//return null; //TODO setConnectorRoleWindows
	}
	private void setConnectorRoleLinux(String essid,String configPath/*GenericNetworkInterface externalInterface*/)throws Exception{
		// XXX testare setConnectorRoleLinux
		class PeerConnectorThread extends Thread{
			private IEEE80211 ieee80211;
			private String essid;
			private String configPath; 
			//GenericNetworkInterface externalInterface;
			PeerConnectorThread(IEEE80211 ieee80211,String essid,String configPath/*,GenericNetworkInterface externalInterface*/){
				this.ieee80211=ieee80211;
				this.essid=essid;
				this.configPath=configPath;
				//this.externalInterface=externalInterface;
			}
			public void run(){
				try{
					System.out.println("IEEE80211 setConnectorRoleLinux: this.getDescription() "+ieee80211.getDescription());
					//System.out.println("IEEE80211 setConnectorRoleLinux: externalInterface.getDescription() "+externalInterface.getDescription());
					Process if8=Runtime.getRuntime().exec("kill `ps auwx | grep '"+DHCLIENT+" "+ieee80211.getDescription()+"' | awk '{print( $2 )}'`");
					if8.waitFor(); if8.destroy();
					//System.err.println("kill `ps auwx | grep '"+DHCLIENT+" "+ieee80211.getDescription()+"' | awk '{print( $2 )}'`");

					Process if1=Runtime.getRuntime().exec("ifconfig "+ieee80211.getDescription()+" "+connectorRoleIP);
					if1.waitFor(); if1.destroy();
					
					// XXX this command should be not necessary: added to overcome a 2.6.27 kernel bug
					Process if0=Runtime.getRuntime().exec("ifconfig "+ieee80211.getDescription()+" down");
					if0.waitFor(); if0.destroy();
					
					Process iw1=Runtime.getRuntime().exec("iwconfig "+ieee80211.getDescription()+" mode Ad-Hoc");
					iw1.waitFor(); iw1.destroy();

					// XXX this command should be not necessary: added to overcome a 2.6.27 kernel bug
					Process if2=Runtime.getRuntime().exec("ifconfig "+ieee80211.getDescription()+" up");
					if2.waitFor(); if2.destroy();
					
					Process iw2=Runtime.getRuntime().exec("iwconfig "+ieee80211.getDescription()+" essid "+essid);
					iw2.waitFor(); iw2.destroy();
					//notAllowedESSIDs.add(new Location(essid));
					Process iw3=Runtime.getRuntime().exec("iwconfig "+ieee80211.getDescription()+" channel 7");
					iw3.waitFor(); iw3.destroy();
					Process iw4=Runtime.getRuntime().exec("iwconfig "+ieee80211.getDescription()+" rate 11M");
					iw4.waitFor(); iw4.destroy();
					Process iw5=Runtime.getRuntime().exec("iwconfig "+ieee80211.getDescription()+" enc off");
					iw5.waitFor(); iw5.destroy();
					Process k2=Runtime.getRuntime().exec("killall "+DHCPDAEMON);
					k2.waitFor(); k2.destroy();
					
					//Process if4=Runtime.getRuntime().exec("dhclient -1 "+ieee80211.getDescription());
					//if4.waitFor(); if4.destroy();
					
					//ripeto perchè a volte prende strani indirizzi...
					
					
					Process k9=Runtime.getRuntime().exec("killall "+DHCPDAEMON);
					k9.waitFor(); k9.destroy();

					// reset state
//					Runtime.getRuntime().exec("iptables -F");
//					Runtime.getRuntime().exec("iptables -t nat -F");
//					Runtime.getRuntime().exec("iptables -t mangle -F");
//					Runtime.getRuntime().exec("iptables -X");
					
					
					//Runtime.getRuntime().exec("echo \"1\" > /proc/sys/net/ipv4/ip_forward");
//					Runtime.getRuntime().exec("sysctl -w net.ipv4.ip_forward=1");
					
//					Runtime.getRuntime().exec("echo \"1\" > /proc/sys/net/ipv4/ip_dynaddr");
					/*p=Runtime.getRuntime().exec("cat /proc/sys/net/ipv4/ip_forward");
					stream = new BufferedInputStream(p.getInputStream());
					c = stream.read();
					System.out.print("cat /proc/sys/net/ipv4/ip_forward\t");
					while(c!=-1 ){
						System.out.print(""+(char)c);
						c = stream.read();
					}*/

// LA SEGUENTE PARTE IN ROUTING MANAGER
//					String external=externalInterface.getDescription();
//					if(external.equals("hci0")){
//						external="bnep0";
//					}
//					
//					Process p=Runtime.getRuntime().exec("iptables -A FORWARD -i "+ieee80211.getDescription()+" -o "+external+" -j ACCEPT");
//					p.waitFor(); p.destroy();
//					p=Runtime.getRuntime().exec("iptables -A FORWARD -o "+ieee80211.getDescription()+" -i "+external+" -j ACCEPT");
//					p.waitFor(); p.destroy();
//					p=Runtime.getRuntime().exec("iptables -A INPUT -i "+ieee80211.getDescription()+" -j ACCEPT");
//					p.waitFor(); p.destroy();
//					p=Runtime.getRuntime().exec("iptables -A INPUT -i "+external+" -j ACCEPT");
//					p.waitFor(); p.destroy();
//					p=Runtime.getRuntime().exec("iptables -A OUTPUT -o "+ieee80211.getDescription()+" -j ACCEPT");
//					p.waitFor(); p.destroy();
//					p=Runtime.getRuntime().exec("iptables -A OUTPUT -o "+external+" -j ACCEPT");
//					p.waitFor(); p.destroy();
					/*stream = new BufferedInputStream(p.getInputStream());
					c = stream.read();
					while(c!=-1 ){
						System.out.print(""+(char)c);
						c = stream.read();
					}*/
//					p=Runtime.getRuntime().exec("iptables -t nat -A POSTROUTING -o "+external+" -s 192.168.128.0/24 -j MASQUERADE");
//					p.waitFor(); p.destroy();
					/*stream = new BufferedInputStream(p.getInputStream());
					c = stream.read();
					while(c!=-1 ){
						System.out.print(""+(char)c);
						c = stream.read();
					}*/
// FINE PARTE DA SPOSTARE
					//Process p=Runtime.getRuntime().exec("iptables -A INPUT -i "+ieee80211.getDescription()+" -j ACCEPT");
					//p.waitFor(); p.destroy();
					//p=Runtime.getRuntime().exec("iptables -A OUTPUT -o "+ieee80211.getDescription()+" -j ACCEPT");
					//p.waitFor(); p.destroy();
					
					//preparazione file di configurazione del server DHCP
					//copia del template nel file di configurazione
					String configFilename=configPath+"dhcpd.conf";
//metodo con il mac dato che capita che prendesse il proprio indirizzo!!!
					makeDhcpdConf(connectorRoleIP,configFilename,ieee80211.hardwareAddress);
					
					String command1=DHCPDAEMON+" "+ieee80211.getDescription()+" -cf "+configFilename+" -f -d";
					System.out.println("IEEE80211.setConnectorRoleLinux command1: "+command1);
					Process p1=
					Runtime.getRuntime().exec(command1);
//					Process if7=Runtime.getRuntime().exec(DHCLIENT+" -r "+ieee80211.getDescription());
//					if7.waitFor(); if7.destroy();
					Process if3=Runtime.getRuntime().exec("ifconfig "+ieee80211.getDescription()+" "+connectorRoleIP);
					if3.waitFor(); if3.destroy();
					connectRoleEssid=essid;
					
					//p1.waitFor();
					/**/InputStream stream = new BufferedInputStream(p1.getErrorStream());
					//InputStream stderrStream1 = new BufferedInputStream(p1.getErrorStream());
					//StringBuffer buffer1= new StringBuffer();

					if(logging){
						logger.info("IEEE80211.setConnectorRoleLinux peer connector ready");
					}
					
					int c = stream.read();
					//int ce1 = stderrStream1.read();
					while(c!=-1 ){
						System.out.print(""+(char)c);
						//System.err.print(""+(char)ce1);
						//buffer1.append((char)c1);
						c = stream.read();
						//ce1 = stderrStream1.read();
					}/**/
				}
				catch(Exception e){
					e.printStackTrace();
				}
				System.out.println("IEEE80211 setConnectorRoleLinux: finish");
			}
		}
		new PeerConnectorThread(this,essid,configPath/*,externalInterface*/).start();
	}
	
	public void resetConnectorRole()throws Exception{
		if(connectorRole==true){
			for(int i=0;i<notAllowedESSIDs.size();i++){
				if(notAllowedESSIDs.elementAt(i).getId().equalsIgnoreCase(connectRoleEssid)){
					notAllowedESSIDs.removeElementAt(i);
					i--;}
			}
			if(System.getProperty("os.name").startsWith("Linux")){
				resetConnectorRoleLinux();
			}
			else if(System.getProperty("os.name").startsWith("Windows")){	
				resetConnectorRoleWindows();
			}
			else{
				throw new Exception("Not supported Operating System");
			}
			connectorRole=false;
		}
	}
	private void resetConnectorRoleWindows()throws Exception{
		throw new Exception("IEEE80211.resetConnectorRoleWindows not implemented: ");
		//return null; //TODO resetConnectorRoleWindows
	}
	private void resetConnectorRoleLinux()throws Exception{
		//XXX testare resetConnectorRoleLinux
		
		// reset state
		
		/*Runtime.getRuntime().exec("sysctl -w net.ipv4.ip_forward=0");
		Runtime.getRuntime().exec("echo \"0\" > /proc/sys/net/ipv4/ip_dynaddr");
		
		Runtime.getRuntime().exec("iptables -F");
		Runtime.getRuntime().exec("iptables -t nat -F");
		Runtime.getRuntime().exec("iptables -t mangle -F");
		Runtime.getRuntime().exec("iptables -X");*/
		
		// XXX this command should be not necessary: added to overcome a 2.6.27 kernel bug 
		Process if0=Runtime.getRuntime().exec("ifconfig "+super.getDescription()+" down");
		if0.waitFor(); if0.destroy(); 
		
		Process iw1=Runtime.getRuntime().exec("iwconfig "+super.getDescription()+" mode Managed");
		iw1.waitFor(); iw1.destroy();

		// XXX this command should be not necessary: added to overcome a 2.6.27 kernel bug 
		Process if1=Runtime.getRuntime().exec("ifconfig "+super.getDescription()+" up");
		if1.waitFor(); if1.destroy(); 
		
		Process iw2=Runtime.getRuntime().exec("iwconfig "+super.getDescription()+" essid any");
		iw2.waitFor(); iw2.destroy();
		Process iw3=Runtime.getRuntime().exec("iwconfig "+super.getDescription()+" ap any");
		iw3.waitFor(); iw3.destroy();
		Process iw4=Runtime.getRuntime().exec("iwconfig "+super.getDescription()+" channel any");
		iw4.waitFor(); iw4.destroy();
		Process iw5=Runtime.getRuntime().exec("iwconfig "+super.getDescription()+" rate auto");
		iw5.waitFor(); iw5.destroy();
		Process k3=Runtime.getRuntime().exec("killall "+DHCPDAEMON);
		k3.waitFor(); k3.destroy();
		
	}
	
	
	public String connect(BSS bss)throws Exception{
		
		System.out.println("IEEE802.11.connect bss "+bss);
		if(System.getProperty("os.name").startsWith("Linux")){
			return connectLinux(bss);
		}
		else if(System.getProperty("os.name").startsWith("Windows")){	
			return connectWindows(bss);
		}
		else{
			throw new Exception("Not supported Operating System");
		}
		
		
	}
	private String connectWindows(BSS bss)throws Exception{
		if(bss.getType()==BSS.ADHOC){
			this.setBssid(bss);
		}
		else{
			this.setEssid(bss);
		}
		
		// DHCP client
		String command="ipconfig /renew \""+super.getName()+"\"";
		System.out.println("80211: connectWindows command "+command);
		Process p1;
		p1= Runtime.getRuntime().exec(command);
		//p1.waitFor();
		
		InputStream stdoutStream1 = new BufferedInputStream(p1.getInputStream());
		StringBuffer buffer1= new StringBuffer();
		int c1 = stdoutStream1.read();
		while(c1!=-1){
			buffer1.append((char)c1);
			c1 = stdoutStream1.read();
		}
		String outputText1 = buffer1.toString();
		System.out.println("\toutputText1 "+outputText1);
		// TODO connectWindows: return new IP address
		return null;
	}
	private String connectLinux(BSS bss)throws Exception{
		//String ipAddress=null;
		notAllowedESSIDs.add(new Location(bss.getEssid()));
		// XXX this command should be not necessary: added to overcome a 2.6.27 kernel bug
		Process if0=Runtime.getRuntime().exec("ifconfig "+getDescription()+" down");
		if0.waitFor(); if0.destroy();
		if(bss.getType()==BSS.ADHOC){
			String command="iwconfig "+super.getDescription()+" mode Ad-Hoc essid "+bss.getEssid();
//			System.out.println("80211: connectLinux command "+command);
			Runtime.getRuntime().exec(command);
			//this.setBssid(bss);
			this.setEssid(bss);
		}
		else{
			String command="iwconfig "+super.getDescription()+" mode Managed";
//			System.out.println("80211: connectLinux command "+command);
			Runtime.getRuntime().exec(command);
			this.setEssid(bss);
		}
		//XXX this command should be not necessary: added to overcome a 2.6.27 kernel bug
		Process if1=Runtime.getRuntime().exec("ifconfig "+getDescription()+" up");
		if1.waitFor(); if1.destroy();
		
		// (could be even both setBssid and setEssid)
		//this.setEssid(bss);
		//this.setBssid(bss);
		if(logging){
			logger.info("IEEE80211.connect connected "+bss.getId());
		}
		

		// DHCP client
		//String command="dhclient "+super.getDescription();
		/*String command2="dhclient -1 "+super.getDescription(); // only the first attempt
		System.out.println("80211: connectLinux command2 "+command2);
		Process p2;
		p2= Runtime.getRuntime().exec(command2);
		//p2.waitFor();
		
		InputStream stderrStream2 = new BufferedInputStream(p2.getErrorStream());
		StringBuffer bufferErr2= new StringBuffer();
		int cErr2 = stderrStream2.read();
		while(cErr2!=-1){
			bufferErr2.append((char)cErr2);
			cErr2 = stderrStream2.read();
		}
		String outputErrText2 = bufferErr2.toString();
		System.out.println("\t\toutputErrText2\n"+outputErrText2);
		
		// Look for the new IP address
		String[] lines=outputErrText2.split("[\n]");
		for(int i=0;i<lines.length;i++){
			if(lines[i].startsWith("bound to")){
				ipAddress=lines[i].split(" ")[2];
			}
		}*/

		String ipAddress=null;
		/*String command1="ifconfig "+super.getDescription();
//		System.out.println("\tcommand1: "+command1);
		Process p1=
		Runtime.getRuntime().exec(command1);
		p1.waitFor();
		InputStream stdoutStream1 = new BufferedInputStream(p1.getInputStream());
		StringBuffer buffer1= new StringBuffer();
		int c1 = stdoutStream1.read();
		while(c1!=-1){
			buffer1.append((char)c1);
			c1 = stdoutStream1.read();
		}
		String outputText1 = buffer1.toString();
//		System.out.println("\toutputText1:\n"+outputText1);
		
		if(outputText1.contains("inet addr")){
			String lines[]=outputText1.split("[\n]");
			for(int i=0; i<lines.length && ipAddress==null; i++){
				if(lines[i].contains("inet addr")){
					String[] tokens=lines[i].split("[: ]");
					for(int j=0; j<tokens.length &&  ipAddress==null; j++){
						//System.out.println( "tokens["+j+"] "+tokens[j] );
						if(tokens[j].equals("inet") && tokens[j+1].equals("addr")){
							ipAddress=tokens[j+2];
						}
					}
				}
			}
			System.out.println("dhclient old ipAddress: "+ipAddress);
		}
		else{*/
			String command4="ps -e|grep dhc";
//			System.out.println("IEEE80211 connectLinux command4: "+command4);
			Process p4=
			Runtime.getRuntime().exec(command4);
			InputStream stdoutStream4 = new BufferedInputStream(p4.getInputStream());
			//InputStream stdoutStream4 = new BufferedInputStream(p4.getErrorStream());
			StringBuffer buffer4= new StringBuffer();
			int c4 = stdoutStream4.read();
			while(c4!=-1){
				buffer4.append((char)c4);
				c4 = stdoutStream4.read();
			}
			String outputText4 = buffer4.toString();
//			System.out.println("dhclient outputText4: "+outputText4);
			
			if(outputText4.contains(DHCLIENT)){
				// do nothing!
				// another dhclient is running...
				// TODO maybe synchronize this method...
			}
			else{
				Thread.sleep(1000);
				// faccio partire dhclient su quell'interfaccia!
				//String command2="dhclient -1 "+interfaceName;
				if(connectorRole){
					Process if8=Runtime.getRuntime().exec("kill `ps auwx | grep '"+DHCLIENT+" "+super.getDescription()+"' | awk '{print( $2 )}'`");
					if8.waitFor(); if8.destroy();
					//System.err.println("kill `ps auwx | grep '"+DHCLIENT+" "+super.getDescription()+"' | awk '{print( $2 )}'`");
					Process if3=Runtime.getRuntime().exec("ifconfig "+super.getDescription()+" "+connectorRoleIP);
					if3.waitFor(); if3.destroy();
				}else{
				String command2=DHCLIENT+" "+super.getDescription();
				System.out.println("IEEE80211 setConnectorRoleLinux command2: "+command2);
				Process p2=
				Runtime.getRuntime().exec(command2);
				//InputStream stdoutStream2 = new BufferedInputStream(p2.getInputStream());
				InputStream stdoutStream2 = new BufferedInputStream(p2.getErrorStream());
				StringBuffer buffer2= new StringBuffer();
				int c2 = stdoutStream2.read();
				while(c2!=-1){
					buffer2.append((char)c2);
					c2 = stdoutStream2.read();
				}
				String outputText2 = buffer2.toString();
				System.out.println("dhclient outputText2: "+outputText2);
				
				// recupero il nuovo ip
				ipAddress=null;
				String lines[]=outputText2.split("[\n]");
				for(int i=0;i<lines.length && ipAddress==null;i++){
					if(lines[i].startsWith("bound to")){
						String tokens[]=lines[i].split("[ ]");
						ipAddress=tokens[2];
					}
				}
				System.out.println("dhclient new ipAddress: "+ipAddress);
				}
			}
		/*}*/
		
		if(logging){
			logger.info("IEEE80211.connect channeled "+bss.getId()+" "+ipAddress);
		}
//		System.out.println("\tnew IP address "+ipAddress);
		//System.exit(0);
		return ipAddress;
	}
	
	public synchronized Vector<NamedLocationOss> getRSSIList()throws Exception{
		// synchornized: if two requests are almost simultaneous,
		// the first one is actually accomplished,
		// the second one receives the cached results of the first one.
		//System.out.println("IEEE80211.getRSSIList start ");
		
		if(lastRSSIScan==-1 || System.currentTimeMillis()-lastRSSIScan>200){
			// NOTE: too frequent RSSI scans may give problems to the wireless interface
			// ==> RSSI scan at most every 0.2s
			
			//System.out.println("------ privateCachedRSSIVector "+lastRSSIScan+" "+System.currentTimeMillis());
			//return (Vector<LocationOss>)(privateCachedRSSIVector.clone());
			//retoutputTexturn privateCachedRSSIVector;
		//}
		//else{
			//System.out.println("++++++ privateRSSIVector "+lastRSSIScan+" "+System.currentTimeMillis());
			Vector<NamedLocationOss> privateRSSIVector;
			//if(wirelessDevice.getNumber()==-1){
/*			if(super.getName().equalsIgnoreCase("Simulator")){//.getNumber()==-1){
				//System.out.println("Simulation!!!");
				privateRSSIVector = getRSSIListSimulator();
			}
			else*/ if(System.getProperty("os.name").startsWith("Linux")){
				privateRSSIVector = getRSSIListLinux();
			}
			else if(System.getProperty("os.name").startsWith("Windows")){	
				privateRSSIVector = getRssiListWindows();
			}
			else{
				throw new Exception("Not supported Operating System");
			}
			//RSSIVector=privateRSSIVector;
			privateCachedRSSIVector=privateRSSIVector;
			lastRSSIScan=System.currentTimeMillis();
			//return privateRSSIVector;
			
			if(testing){
				// delete/neglect remote interfaces not listed in "allowedMACs"
				for(int i=0;i<privateCachedRSSIVector.size();i++){
					//String mac=privateCachedRSSIVector.elementAt(i).getId().toLowerCase().replaceAll(":", "");
					String essid=((BSS)(privateCachedRSSIVector.elementAt(i))).getEssid();
					//System.out.println("IEEE80211.getRSSIList found "+mac);
					//String mac=((BSS)(privateCachedRSSIVector.elementAt(i)))
					boolean allowed=false;
					 
					for(int j=0;j<allowedESSIDs.size();j++){
						//System.out.println("\t"+allowedMACs.elementAt(j).getId());
						//if(allowedMACs.elementAt(j).getId().equals(mac)){
						if(essid.startsWith(allowedESSIDs.elementAt(j).getId())){
							//System.out.println("\t\tallowed "+allowedESSIDs.elementAt(j).getId());
					
							
							
							allowed=true;
							
						}
					}
					if(!allowed){
						//System.out.println("\t\tdeleting "+mac);
						privateCachedRSSIVector.removeElementAt(i);
						i--;
					}
					
					boolean notAllowed=false;
					for(int m=0;m<notAllowedESSIDs.size();m++){
						if(essid.equals(notAllowedESSIDs.elementAt(m).getId())){
							notAllowed=true;
							}
						
					}
					if(notAllowed){
						privateCachedRSSIVector.removeElementAt(i);
						i--;
					}
						
			
				}
			}
		}
		if(logging){
			for (int i=0;i<privateCachedRSSIVector.size();i++){
				logger.info("IEEE80211.getRSSIList found "+privateCachedRSSIVector.elementAt(i).getId());
			}
		}
		return new Vector<NamedLocationOss>(privateCachedRSSIVector);
	}
	private synchronized Vector<NamedLocationOss> getRssiListWindows(){
		Vector<NamedLocationOss> v = new Vector<NamedLocationOss>();
		
		try{
			//System.out.println("eseguo: " + cmdarrayWindows[0] + " "+ cmdarrayWindows[1]+ " " + _scheda.getNumero());
			Process process = Runtime.getRuntime().exec("./lib/80211UtilWindows "+super.windowsNumber+" getBssList ");
			//Process process = Runtime.getRuntime().exec("./lib/80211UtilWindows "+super.getName().substring(3)+" getBssList ");
			//process.waitFor();
			InputStream stdoutStream = new BufferedInputStream(process.getInputStream());
			
			StringBuffer buffer= new StringBuffer();
			int c = stdoutStream.read();
			while(c!=-1){
				buffer.append((char)c);
				c = stdoutStream.read();
			}
			String outputText = buffer.toString();
			long timestamp=System.currentTimeMillis();
			
			String[] lines=outputText.split("\n");
			for(int i=0;i<lines.length;i++){
				BSS bss=null;
				String tokens[]=lines[i].split(";");
				if(tokens.length>=8){
					//int idEkahau = Integer.parseInt(st.nextToken(delim));
					int channel = Integer.parseInt(tokens[0]);
					//int idEkahau = channel;
					String mac = tokens[1];
					String ssid = tokens[2];
					int rssi = Integer.parseInt(tokens[3]);
					int noise = Integer.parseInt(tokens[4]);
					/*int timestampError = */Integer.parseInt(tokens[5]);
					int type=BSS.UNKNOWN_TYPE;
					if(tokens[6].equals("Ad-Hoc")){
						type=BSS.ADHOC;
					}
					else if(tokens[6].equals("Infrastructure")){
						type=BSS.INFRASTRUCTURE;
					}
					int encryption=BSS.UNKNOWN_TYPE;
					if(tokens[7].equals("None")){
						encryption=BSS.NONE_ENCRYPTION;
					}
					else if(tokens[7].equals("WEP/WPA")){
						// TODO 80211 windows: come fare a capire se e' WEP oppure WPA??? 
						encryption=BSS.UNKNOWN_ENCRYPTION;
					}
					bss = new BSS(/*idEkahau,*/mac,channel,ssid,rssi,noise,timestamp,type,encryption);
				}
				
				if(bss!=null)v.add(bss);
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
		return v;
	}
	private synchronized Vector<NamedLocationOss> getRSSIListLinux(){
		Vector<NamedLocationOss> v = new Vector<NamedLocationOss>();
		 
		String cmd = "iwlist "+super.getDescription()+" scan";
		
		String mac="";
		String rssi="";
		String noise="";
		String id="";
		String essid="";
		String channel="";
		int type=BSS.UNKNOWN_TYPE;
		int encryption=BSS.UNKNOWN_ENCRYPTION;
		try{
			//System.out.println("getRSSIListLinux execute: "+cmd );
			Process process = Runtime.getRuntime().exec(cmd);
			//process.waitFor();
			BufferedInputStream stdoutStream = new BufferedInputStream(process.getInputStream());
			//InputStream stdoutStream = process.getInputStream();

			StringBuffer buffer= new StringBuffer();
			//System.out.println("IEEE80211: pre read() available()="+stdoutStream.available());
			int c = stdoutStream.read();
			while(c!=-1){
				buffer.append((char)c);
				c = stdoutStream.read();
			}
			//System.out.println("IEEE80211: post read() ");
			
			String outputText = buffer.toString();
			long timestamp=System.currentTimeMillis();
			String[] lines=outputText.split("[\n]");
			//System.out.println("lines.length "+lines.length);
			for(int i=0;i<lines.length;i++){
				//System.out.println("lines["+i+"] "+lines[i]);
				if(lines[i].contains("Cell")){
					
					if(i>1){
						int intNoise;
						try{
							if(noise.equals(""))
								intNoise=0;
							else
							intNoise=Integer.parseInt(noise);
						}
						catch(NumberFormatException nfe){
							if(rssi.contains("/")){
								String[] rssitok=rssi.split("/");
								int realrssi= Integer.valueOf(rssitok[0]);
								realrssi= realrssi-110;
								rssi=""+realrssi;
								
							}
							//System.out.println("Questo è l'rssi: "+rssi);
							intNoise=Integer.parseInt(rssi);
						}
						int intChannel;
						try{
							intChannel=Integer.parseInt(channel);
						}
						catch(NumberFormatException nfe){
							intChannel=0;
						}
						BSS ap = new BSS(
								//Integer.parseInt(id),
								mac,
								intChannel,
								essid,
								Integer.parseInt(rssi),
								intNoise,
								timestamp,
								type,
								encryption
							);
						
						v.add(ap);
						mac="";
						rssi="";
						noise="";
						id="";
						essid="";
						channel="";
						type=BSS.UNKNOWN_TYPE;
						encryption=BSS.UNKNOWN_ENCRYPTION;
					}
					
					String[]tokens=lines[i].split("[ \n]");
					//id=tokens[1];
					for(int j=0;j<tokens.length;j++){
						//System.out.println("Cell "+j+" "+tokens[j]);
						if(tokens[j].equals("Address:")){
							if(!mac.equals(""))throw new Exception("mac should not be "+mac);
							mac=tokens[j+1];
							//System.out.println("mac "+mac);
						}
						if(tokens[j].equals("Cell")){
							if(!id.equals(""))throw new Exception("id should not be "+id);
							id=tokens[j+1];
							//System.out.println("id "+id);
						}
					}
				}
				else if(lines[i].contains("ESSID:")){
					String[]tokens=lines[i].split("[ \"]");
					for(int r=0;r<tokens.length;r++){
						//System.out.println("ESSID "+j+" "+tokens[j]);
						if(tokens[r].equals("ESSID:")){
							//System.out.println("ESSID "+tokens[j+1]);
							if(!essid.equals(""))throw new Exception("essid should not be "+essid);
							int j=r;
							essid=tokens[j+1];
							//System.out.println("essid "+essid);
						}
					}
				}
				else if(lines[i].contains("Channel:")){
					try{
						String[]tokens=lines[i].split("[ ():]");
						for(int j=0;j<tokens.length;j++){
							//System.out.println("Frequency "+j+" "+tokens[j]);
							if(tokens[j].equals("Channel")){
								if(!channel.equals(""))throw new Exception("channel should not be "+channel);
								channel=tokens[j+1];
								//System.out.println("channel "+channel);
							}
						}
					}
					catch(Exception e){
						// try/catch added due to problems with ipw2200 driver (Linux-debian),
						// i.e., sometimes the same cell has two different channels,
						// the first one right, the second one (usually 0) wrong.
						e.printStackTrace();
					}
				}
				else if(lines[i].contains("Signal")){
					String[]tokens=lines[i].split("[ :=]");
					for(int j=0;j<tokens.length;j++){
						//System.out.println("Signal "+j+" "+tokens[j]);beginIndex
						if(tokens[j].equals("Signal")&&tokens[j+1].equals("level")){
							if(!rssi.equals(""))throw new Exception("rssi should not be "+rssi);
							rssi=tokens[j+2];
							//Giorgio chiavetta digicom prende il segna level in percentuale
							if(rssi.contains("/")){
								String[] rssitok=rssi.split("/");
								int realrssi= Integer.valueOf(rssitok[0]);
								realrssi= realrssi-110;
								rssi=""+realrssi;
							}
						
							j=j+2;
							//System.out.println("rssi "+rssi);
						}
						if(tokens[j].equals("Noise")&&tokens[j+1].equals("level")){
							if(!noise.equals(""))throw new Exception("noise should not be "+noise);
							noise=tokens[j+2];
							j=j+2;
							//System.out.println("noise "+noise);
						}
					}
				}
				else if(lines[i].contains("Mode:")){
					String[]tokens=lines[i].split("[:]",2);
					if(type!=BSS.UNKNOWN_TYPE)throw new Exception("type should be UNKNOWN");
					if(tokens[1].equals("Master")){
						type=BSS.INFRASTRUCTURE;
					}
					else if(tokens[1].equals("Ad-Hoc")){
						type=BSS.ADHOC;
					}
					/*else{
						type=BSS.UNKNOWN;
					}*/
				}
				else if(lines[i].contains("Encryption")){
					String[]tokens=lines[i].split("[:]",2);
					if(encryption!=BSS.UNKNOWN_ENCRYPTION)throw new Exception("encryption should be UNKNOWN");
					if(tokens[1].equals("off")){
						encryption=BSS.NONE_ENCRYPTION;
					}
					else{
						encryption=BSS.WEP;
					}
				}
				else if(encryption!=BSS.NONE_ENCRYPTION){
					if(lines[i].contains("WPA")){
						encryption=BSS.WPA;
					}
				}
				
				/*if(!mac.equals("") && !rssi.equals("") && !noise.equals("") 
						&& !id.equals("")	&& !channel.equals("") 
						&& !essid.equals("") && type!=BSS.UNKNOWN_TYPE
						&& encryption!=BSS.UNKNOWN_ENCRYPTION ){
					BSS ap = new BSS(
							//Integer.parseInt(id),
							mac,
							Integer.parseInt(channel),
							essid,
							Integer.parseInt(rssi),
							Integer.parseInt(noise),
							timestamp,
							type,
							encryption
						);
					v.add(ap);
					mac="";
					rssi="";
					noise="";
					id="";
					essid="";
					channel="";
					type=BSS.UNKNOWN_TYPE;
					encryption=BSS.UNKNOWN_ENCRYPTION;
				}*/
			}
			//System.out.println("IEEE80211.getRssiListLinux lines.length "+lines.length);
			if(lines.length>1){
				int intNoise;
				try{
					intNoise=Integer.parseInt(noise);
				}
				catch(NumberFormatException nfe){
					
					if(rssi.contains("/")){
						String[] rssitok=rssi.split("/");
						int realrssi= Integer.valueOf(rssitok[0]);
						realrssi= realrssi-110;
						rssi=""+realrssi;
					}
					intNoise=Integer.parseInt(rssi);
				}
				int intChannel;
				try{
					intChannel=Integer.parseInt(channel);
				}
				catch(NumberFormatException nfe){
					intChannel=0;
				}
				BSS ap = new BSS(
						//Integer.parseInt(id),
						mac,
						intChannel,
						essid,
						Integer.parseInt(rssi),
						intNoise,
						timestamp,
						type,
						encryption
					);
				
				v.add(ap);
			}
		}		
		catch(Exception e){
			System.out.println("mac "+mac+"  rssi "+rssi +"  noise "+noise+"  id "+id+"  essid "+essid+"  channel "+channel+"  type "+type+"  encryption "+encryption);
			e.printStackTrace();
		}
		//System.out.println("IEEE80211.getRssiListLinux v "+v);
		return v;
	}
/*	private synchronized Vector<NamedLocationOss> getRSSIListSimulator()
	{
		Vector<NamedLocationOss> rssiVector=deviceData.getRssiDB();
		Vector<NamedLocationOss> rssiVectorAP=new Vector<NamedLocationOss>();
		long timestamp=System.currentTimeMillis();
		for(int i=0;i<rssiVector.size();i++){
			LocationOss tempLO=rssiVector.elementAt(i);
			rssiVectorAP.addElement(
					new BSS(
							//i+1,
							tempLO.getId(),
							i+1,
							"sim",
							(int)(tempLO.getValue()),
							-128,
							timestamp,
							BSS.INFRASTRUCTURE,
							BSS.NONE_ENCRYPTION
						)
				);
		}
		return rssiVectorAP;
	}
*/	
	
	
	public String getBSSID()throws Exception{
		String bssid;
/*		if(super.getName().equalsIgnoreCase("Simulator")){//.getNumber()==-1){
			//System.out.println("Simulation!!!");
			bssid = getBSSIDSimulator();
		}
		else*/ if(System.getProperty("os.name").startsWith("Linux")){
			bssid = getBSSIDLinux();
		}
		else if(System.getProperty("os.name").startsWith("Windows")){	
			bssid = getBSSIDWindows();
		}
		else{
			throw new Exception("Not supported Operating System");
		}
		return bssid;
	}
/*	private String getBSSIDSimulator(){
		return deviceData.getCurrentAP().getId();
	}
*/
	private String getBSSIDWindows(){
		String bssid=null;
		try{
			String command="./lib/80211UtilWindows "+super.windowsNumber+" getBssid ";
			System.out.println("IEEE80211 getBSSIDWindows: " + command);
			Process process = Runtime.getRuntime().exec(command);
			//Process process = Runtime.getRuntime().exec("./lib/80211UtilWindows "+super.getName().substring(3)+" getBssid ");
			process.waitFor();
			InputStream stdoutStream = new BufferedInputStream(process.getInputStream());
			
			StringBuffer buffer= new StringBuffer();
			int c = stdoutStream.read();
			while(c!=-1){
				buffer.append((char)c);
				c = stdoutStream.read();
			}
			String outputText = buffer.toString();
			System.out.println("getBSSIDWindows outputText: "+outputText);
			
			String[] lines=outputText.split("\n");
			String[] tokens=lines[0].split(" ");
			bssid=tokens[1];
			
		}
		catch(Exception e){
			e.printStackTrace();
		}
		return bssid;
	}
	private String getBSSIDLinux(){
		String bssid=null;
		
		String[] cmdarray = new String[2];
		cmdarray[0] = "iwconfig";
		//cmdarray[1] = "eth"+super.getNumber();
		cmdarray[1] = super.getName();
		
		try{
			//System.out.println("getRSSILinux eseguo: " + cmdarray[0] + " "+ cmdarray[1] +" " + cmdarray[2] );
			Process process = Runtime.getRuntime().exec(cmdarray);
			process.waitFor();
			InputStream stdoutStream = new BufferedInputStream(process.getInputStream());
			//BufferedReader br = new BufferedReader(new InputStreamReader( process.getInputStream() ));

			StringBuffer buffer= new StringBuffer();
			int c = stdoutStream.read();
			while(c!=-1){
				buffer.append((char)c);
				c = stdoutStream.read();
			}

			String outputText = buffer.toString();
			String[] lines=outputText.split("\n");
			for(int i=0;i<lines.length && bssid==null;i++){
				//System.out.println(i+" "+lines[i]);
				if(lines[i].contains("Access Point")){
					String[]tokens=lines[i].split("[ \n]");
					//id=tokens[1];
					for(int j=0;j<tokens.length;j++){
						//System.out.println("Cell "+j+" "+tokens[j]);
						if(tokens[j].equals("Point:")){
							bssid=tokens[j+1];
							//System.out.println("mac "+mac);
						}
					}
				}
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
		return bssid;
	}

	public void setBssid(BSS bss)throws Exception{
		if(System.getProperty("os.name").startsWith("Linux")){
			setBssidLinux(bss);
		}
		else if(System.getProperty("os.name").startsWith("Windows")){	
			setBssidWindows(bss);
		}
		else{
			throw new Exception("Not supported Operating System");
		}
	}
	private void setBssidWindows(BSS bss)throws Exception{
		// XXX testare setBssidWindows: considerare WEP/WPA
		Process process = Runtime.getRuntime().exec("./lib/80211UtilWindows "+super.windowsNumber+" setBssid "+bss.getMac());
		//Process process = Runtime.getRuntime().exec("./lib/80211UtilWindows "+super.getName().substring(3)+" setBssid "+bss.getMac());
		process.waitFor();
		/*InputStream stdoutStream = new BufferedInputStream(process.getInputStream());
		
		StringBuffer buffer= new StringBuffer();
		int c = stdoutStream.read();
		while(c!=-1){
			buffer.append((char)c);
			c = stdoutStream.read();
		}
		String outputText = buffer.toString();
		System.out.println("getBSSIDWindows outputText: "+outputText);*/
	}
	private void setBssidLinux(BSS bss)throws Exception{
		String key="";
		if(bss.getEncryption()==BSS.NONE_ENCRYPTION){
			key=" off ";
		}
		else if(bss.getEncryption()==BSS.WEP){
			key="s:"+bss.getWEPKey();
		}
		else if(bss.getEncryption()==BSS.WPA){
			// TODO setBssidLinux: WPA connect
			// For example, see: "wpa_supplicant -Dwext -i"+super.getNumber()+" -c/etc/wpa_supplicant.conf"
		}
		//String command="iwconfig eth"+super.getNumber()+" ap "+bss.getMac()+" key s:"+key;
		String command="iwconfig "+super.getName()+" ap "+bss.getMac()+" key "+key;
		System.out.println("setBssidLinux command: "+command);
		//Process process = 
		Runtime.getRuntime().exec(command);
	}
	
	

	public String getESSID()throws Exception{
		String essid;
		if(super.getName().equalsIgnoreCase("Simulator")){//.getNumber()==-1){
			//System.out.println("Simulation!!!");
			essid = getESSIDSimulator();
		}
		else if(System.getProperty("os.name").startsWith("Linux")){
			essid = getESSIDLinux();
		}
		else if(System.getProperty("os.name").startsWith("Windows")){	
			essid = getESSIDWindows();
		}
		else{
			throw new Exception("Not supported Operating System");
		}
		return essid;
	}
	private String getESSIDSimulator(){
		return "sim";
	}
	private String getESSIDWindows(){
		String essid=null;
		try{
			//System.out.println("eseguo: " + cmdarrayWindows[0] + " "+ cmdarrayWindows[1]+ " " + _scheda.getNumero());
			Process process = Runtime.getRuntime().exec("./lib/80211UtilWindows "+super.windowsNumber+" getEssid");
			//Process process = Runtime.getRuntime().exec("./lib/80211UtilWindows "+super.getName().substring(3)+" getEssid");
			process.waitFor();
			InputStream stdoutStream = new BufferedInputStream(process.getInputStream());
			
			StringBuffer buffer= new StringBuffer();
			int c = stdoutStream.read();
			while(c!=-1){
				buffer.append((char)c);
				c = stdoutStream.read();
			}
			String outputText = buffer.toString();
			//System.out.println("getESSIDWindows outputText: "+outputText);
			
			String[] lines=outputText.split("\n");
			String[] tokens=lines[0].split(" ");
			essid=tokens[1];
			
		}
		catch(Exception e){
			e.printStackTrace();
		}
		return essid;
	}
	private String getESSIDLinux(){
		String essid=null;
		
		/*String[] cmdarray = new String[2];
		cmdarray[0] = "iwconfig";
		//cmdarray[1] = "eth"+super.getNumber();
		cmdarray[1] = super.getName();*/
		
		String cmd="iwconfig "+super.getName();
		
		try{
			//System.out.println("getRSSILinux eseguo: " + cmdarray[0] + " "+ cmdarray[1] +" " + cmdarray[2] );
			Process process = Runtime.getRuntime().exec(cmd);
			process.waitFor();
			InputStream stdoutStream = new BufferedInputStream(process.getInputStream());
			//BufferedReader br = new BufferedReader(new InputStreamReader( process.getInputStream() ));

			StringBuffer buffer= new StringBuffer();
			int c = stdoutStream.read();
			while(c!=-1){
				buffer.append((char)c);
				c = stdoutStream.read();
			}

			String outputText = buffer.toString();
			String[] lines=outputText.split("\n");
			for(int i=0;i<lines.length && essid==null;i++){
				//System.out.println(i+" "+lines[i]);
				if(lines[i].contains("ESSID")){
					String[]tokens=lines[i].split("[ \"\n]");
					//id=tokens[1];
					for(int j=0;j<tokens.length;j++){
						//System.out.println("Cell "+j+" "+tokens[j]);
						if(tokens[j].equals("ESSID:")){
							if(tokens.length>j+1){
								essid=tokens[j+1];
								//System.out.println("mac "+mac);
							}
						}
					}
				}
			}
		}
		catch(Exception e){
			e.printStackTrace();
		}
		return essid;
	}
	public void setEssid(BSS bss)throws Exception{
		if(System.getProperty("os.name").startsWith("Linux")){
			setEssidLinux(bss);
		}
		else if(System.getProperty("os.name").startsWith("Windows")){	
			setEssidWindows(bss);
		}
		else{
			throw new Exception("Not supported Operating System");
		}
	}
	private void setEssidWindows(BSS bss)throws Exception{
		// XXX testare setEssidWindows: considerare WEP/WPA
		Process process = Runtime.getRuntime().exec("./lib/80211UtilWindows "+super.windowsNumber+" setEssid "+bss.getEssid());
		//Process process = Runtime.getRuntime().exec("./lib/80211UtilWindows "+super.getName().substring(3)+" setEssid "+bss.getEssid());
		process.waitFor();
		InputStream stdoutStream = new BufferedInputStream(process.getInputStream());
		
		StringBuffer buffer= new StringBuffer();
		int c = stdoutStream.read();
		while(c!=-1){
			buffer.append((char)c);
			c = stdoutStream.read();
		}
		String outputText = buffer.toString();
		System.out.println("setESSIDWindows outputText: "+outputText);
	}
	private void setEssidLinux(BSS bss)throws Exception{
		String key="";
		if(bss.getEncryption()==BSS.NONE_ENCRYPTION){
			key=" off ";
		}
		else if(bss.getEncryption()==BSS.WEP){
			key="s:"+bss.getWEPKey();
		}
		else if(bss.getEncryption()==BSS.WPA){
			// TODO setEssidLinux: WPA connect
			// For example, see: "wpa_supplicant -Dwext -i"+super.getNumber()+" -c/etc/wpa_supplicant.conf"
		}
		//String command="iwconfig eth"+super.getNumber()+" essid "+bss.getEssid()+" key "+key;
		String command="iwconfig "+super.getName()+" essid "+bss.getEssid()+" key "+key;
//		System.out.println("setESSIDLinux command: "+command);
		//Process process = 
		Runtime.getRuntime().exec(command);
		//process.waitFor();
		/*InputStream stdoutStream = new BufferedInputStream(process.getInputStream());
		StringBuffer buffer= new StringBuffer();
		int c = stdoutStream.read();
		while(c!=-1){
			buffer.append((char)c);
			c = stdoutStream.read();
		}
		String outputText = buffer.toString();
		System.out.println("setESSIDLinux outputText:\n\t"+outputText);
		stdoutStream.close();*/
	}
	
	
	public final static boolean isIEEE80211(GenericNetworkInterface genericNetworkInterface)throws Exception{
		//System.out.println("isIEEE80211 "+genericNetworkInterface);
		boolean res;
		if(System.getProperty("os.name").startsWith("Windows")){
			res=isIEEE80211Windows(genericNetworkInterface);
		}
		else if(System.getProperty("os.name").startsWith("Linux")){	
			res=isIEEE80211Linux(genericNetworkInterface);
		}
		else{
			throw new Exception("Not supported Operating System");
		}
		return res;
	}
	private final static boolean isIEEE80211Windows(GenericNetworkInterface genericNetworkInterface){
		boolean res=false;
		try{
			Process p = Runtime.getRuntime().exec("./lib/80211UtilWindows.exe "+genericNetworkInterface.windowsNumber+" isWireless ");//deviceNumber);
			//System.out.println("isIEEE80211Windows "+genericNetworkInterface.getName().substring(3));
			//Process p = Runtime.getRuntime().exec("./lib/80211UtilWindows.exe "+genericNetworkInterface.getName().substring(3)+" isWireless ");//deviceNumber);
			//p.waitFor();
			InputStream stdoutStream = new BufferedInputStream(p.getInputStream());
			StringBuffer buffer= new StringBuffer();
			int c = stdoutStream.read();
			while(c!=-1){
				buffer.append((char)c);
				c = stdoutStream.read();
			}
			String outputText = buffer.toString();
			stdoutStream.close();
			
			if(outputText.contains("true")) res=true;
		}
		catch(Exception ex) {
			ex.printStackTrace();
		}
		return res;
	}
	private final static boolean isIEEE80211Linux(GenericNetworkInterface genericNetworkInterface) throws IOException {
		//try{
//			System.out.println("isIEEE80211Linux "+genericNetworkInterface);
			//String command="iwconfig eth"+genericNetworkInterface.getNumber();
			String command="iwconfig "+genericNetworkInterface.getDescription();
			//System.out.println("isIEEE80211Linux command: "+command);
			//Process p = Runtime.getRuntime().exec("sudo iwconfig");
			Process p = Runtime.getRuntime().exec(command);
			try{
				p.waitFor();
			}
			catch(Exception ex){
				ex.printStackTrace();
			}
			InputStream stdoutStream = new BufferedInputStream(p.getInputStream());
			 
			StringBuffer buffer= new StringBuffer();
			int c = stdoutStream.read();
			while(c!=-1){
				buffer.append((char)c);
				c = stdoutStream.read();
			}
			String outputText = buffer.toString();
			//System.out.println("isIEEE80211Linux outputText\n"+outputText);
			if(outputText.contains("ESSID")){
				return true;
			}
			else{
				return false;
			}
	}
}

